package com.esdk.sql.orm;

import cn.hutool.json.JSONUtil;
import cn.hutool.json.XML;
import com.alibaba.fastjson.JSONArray;
import com.esdk.esdk;
import com.esdk.exception.SdkRuntimeException;
import com.esdk.interfaces.Adder;
import com.esdk.sql.*;
import com.esdk.utils.*;
import lombok.NonNull;

import java.io.File;
import java.io.IOException;
import java.math.BigDecimal;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
import java.util.function.Function;
import java.util.function.*;
/***
 * @author 范飞宇
 * @since 2006.1.1
 * 用于只读的数据集，不能修改数据集的数量，但注意Row实例是可以修改的。
 */
public class ARowSet<T extends IRow> implements IReadRowSet<T>,Cloneable,ICursor{
	protected transient IResultSet _abrs;
  protected transient int cursor=-1;
  protected String[] columns;
  protected Class<T> _rowCls;
  protected List<T> rowList;
  protected String primaryKeyName;
  protected transient HashMap<String,HashMap<Long,Integer>> uniqueMap;
	private transient int warningSize=esdk.prop.getInteger("abrowset.warningSize",10000);
	private transient int IncreaseWarningSize=esdk.prop.getInteger("abrowset.IncreaseWarningSize",10000);


  public ARowSet(){
    rowList=new ArrayList();
		uniqueMap=null;
  }

  public ARowSet(Class<T> parentRowCls){
    this();
		setParentRowCls(parentRowCls);
  }

  public ARowSet(String[] columns){
    this();
    setColumns(columns);
  }

  public ARowSet(Object[][] array){
    this();
    columns=Arrays.asList(array[0]).toArray(new String[0]);
    for(int i=1;i<array.length;i++){
      add((T)new ABRow((String[])array[0],array[i]));
    }
  }

  public <R extends ParentRow>ARowSet (JSONArray jsarray,@NonNull Class<R> parentRowCls){
    setParentRowCls(parentRowCls);
		load(jsarray);
  }

	public <R extends ParentRow> ARowSet(List<Object> beanList,@NonNull Class<R> parentRowCls){
		this();
		setParentRowCls(parentRowCls);
		try{
			for(int i=0;i<beanList.size();i++){
				R parentRow=createRow();
				parentRow.load(beanList.get(i));
				add((T)parentRow);
			}
		}catch(Exception e){
			throw esdk.tool.wrapThrowble(e);
		}
	}

  public ARowSet(JSONArray jsonArray){
    this();
		load(jsonArray);
  }

  public ARowSet(IResultSet rs,List<T> list) {
  	this(list);
  	if(rs instanceof ARowSet abrs){
		  _abrs=abrs._abrs;
			this._rowCls=abrs._rowCls;
			this.columns=abrs.columns;
			this.primaryKeyName=abrs.primaryKeyName;
	  }
  	else
  		_abrs=rs;
  	setColumns(rs.getColumns());
  }

  public ARowSet(File csvFile) throws IOException{
  	this(EasyStr.fromCsv(EasyFile.loadFromFile(csvFile)));
  }
  public ARowSet(File csvFile,String charset) throws IOException{
  	this(EasyStr.fromCsv(EasyFile.loadFromFile(csvFile,charset,EasyFile._KB)));
  }
  public ARowSet(File csvFile,String charset,boolean forceText) throws IOException{
  	this(EasyStr.fromCsv(EasyFile.loadFromFile(csvFile,charset,EasyFile._KB),forceText));
  }

	public ARowSet(ABResultSet<T> abrs){
		this();
		this._abrs=abrs;
		if(abrs!=null){
			try{
				if(abrs.rs!=null && abrs.rowList.isEmpty()){ //从redis缓存获取的rs是为null的
					TimeMeter tm=TimeMeter.startNew();
					for(T row=abrs.getNextRow();row!=null;row=abrs.getNextRow()){
						rowList.add(row);
					}
					if(abrs.select!=null&&abrs.select.showSql())
						SQLAssistant.showSql(abrs.select,tm,rowList.size());
				}else{
					for(abrs.beforeFirst();abrs.next();){
						rowList.add(abrs.getRow());
					}
				}
			}catch(SQLException e){
				esdk.tool.wrapThrowble(e);
			}
			if(abrs instanceof ParentResultSet prs){
				setParentRowCls(prs._rowCls);
			}else{
				columns=abrs.getColumns();
				setPrimaryKeyName(columns[0]);
			}
		}
	}

  public ARowSet(T[] rows){
    this();
    if(rows.length>0)
      columns=rows[0].getColumns();
    rowList.addAll(Arrays.asList(rows));
  }

  public ARowSet(List<T> list){
    this();
    if(list.isEmpty()==false)
      columns=list.get(0).getColumns();
    rowList.addAll(list);
  }

  public ARowSet(Collection<Map<String,?>> listMap){
    this();
    if(listMap.size()>0) {
    	List<Map<String,?>> list=new ArrayList(listMap);
    	Map<String,?> jo=list.get(0);
    	columns=jo.keySet().toArray(new String[0]);
    	 for(int i=0;i<list.size();i++){
         add((T)new ABRow(list.get(i)));
       }
    }
  }

	protected ARowSet<T> setParentRowCls(@NonNull Class<?> parentRowCls){
		this._rowCls=(Class<T>)parentRowCls;
		ParentRow parentRow=null;
		if(columns==null){
			if(first())
				columns=getFirstRow().getColumns();
			else if(parentRow==null){
				parentRow=((ParentRow)esdk.reflect.safeNewInstance(parentRowCls));
				columns=parentRow.getColumns();
			}
		}
		if(primaryKeyName==null){
			if(first() && getFirstRow() instanceof ParentRow pr)
				primaryKeyName=pr.getPrimaryKeyName();
			else if(parentRow==null){
				parentRow=((ParentRow)esdk.reflect.safeNewInstance(parentRowCls));
				primaryKeyName=parentRow.getPrimaryKeyName();
			}
		}
		return this;
	}

	public ABRowSet load(JSONArray jsonArray){
		rowList.clear();
		if(!jsonArray.isEmpty()) {
			try{
				for(int i=0;i<jsonArray.size();i++){
					T row=createRow();
					row.load(jsonArray.getJSONObject(i));
					add(row);
				}
			}catch(Exception e){
				throw esdk.tool.wrapThrowble(e);
			}
		}
		return (ABRowSet)this;
	}

	protected void checkSize() {
    if(rowList.size()>warningSize) {
    	esdk.swarn(" 请注意：数据集数量已达到{}",warningSize);
    	warningSize+=IncreaseWarningSize;
    }
  }

  private void add(T row){
    rowList.add(row);//注意:多个对象共用一个IRow
    checkSize();
  }

	private void setColumns(String[] columns){
		this.columns=columns;
  }

  protected final boolean isRange(int cursorPos){
    return ABResultSet.isRange(rowList,cursorPos);
  }

  @Override  public String[] getColumns(){
    return columns;
  }

  /**按主键查询记录*/
	public T findById(Object pkid){
		if(pkid==null) return null;
		String pkFieldName=getPrimaryKeyName();
		if(uniqueMap==null || !uniqueMap.containsKey(pkFieldName)) {
			createUniqueIndex(esdk.toArr(pkFieldName));
		}
		Integer pos=getUniqueMap(pkFieldName).get(esdk.obj.longHashCode(pkid));
		return pos!=null?getRow(pos):null;
	}

	/**通过创建索引快速获取记录，只接受等于条件表达式，不能使用大于、小于、in、不等于等表达式
	 * 首次搜索会先创建索引，第二次再搜索就会非常快
	 * @param autoCreateInstance 注意这个空的实例并没有添加到unique索引
	 * */
	public T findByUnique(boolean autoCreateInstance,Object...args) {
		T result=null;
		Map<String,Object> map=findEqConditions(args);
		String[] sortedCols=esdk.array.toArray(map.keySet());
		String columns=esdk.str.valueOf(sortedCols);
		if(uniqueMap==null || !uniqueMap.containsKey(columns)) {
			createUniqueIndex(sortedCols);
		}
  	if(uniqueMap!=null) {
  		Integer rowindex=getUniqueMap(columns).get(esdk.obj.longHashCode(map.values()));
  		if(rowindex!=null)
  			result=this.getRow(rowindex);
  	}
  	if(result==null && autoCreateInstance) {
  		result=createRow();
  		result.load(map);
  	}
  	return result;
	}

	/**生成唯一值索引，注意如果记录被更新，必须手工重新执行，否则会出错误的搜索结果*/
	private Map<Long,Integer> getUniqueMap(String columnsStr) {
		if(uniqueMap==null)
			uniqueMap=new HashMap();
		return esdk.map.getVal(uniqueMap,columnsStr,()->new HashMap());
	}

  /**
   * 生成索引值，用于快速定位
   * 注意：对字段名先排序，以确保用户输入顺序不受限制，但如果字段数量不一致，仍然无法正确使用该索引。
   * */
	public ARowSet<T> createUniqueIndex(String[] columns){
		if(columns.length==0) throw new SdkRuntimeException("索引字段不能为空!");
		String[] sortedCols=esdk.array.sort(columns);
		String sortedColumnsStr=esdk.str.join(sortedCols);
		getUniqueMap(sortedColumnsStr).clear();
		for(int i=0,n=this.size();i<n;i++){
			T row=this.getRow(i);
			List values=row.toList(sortedCols);
			getUniqueMap(sortedColumnsStr).put(esdk.obj.longHashCode(values),i);
		}
		return this;
	}

	public ARowSet<T> recreateUniqueIndex(){
		if(uniqueMap!=null){
			for(String columnsKey: uniqueMap.keySet()){
				String[] cols=columnsKey.split(",");
				createUniqueIndex(cols);
			}
		}
		return this;
	}

	public ARowSet<T> updateUniqueIndex(@NonNull List<T> addedRows){
		if(uniqueMap!=null&&addedRows.isEmpty()==false){
			int index=rowList.size()-addedRows.size();
			for(T addedRow:addedRows){
				for(String columnsKey: uniqueMap.keySet()){
					String[] cols=columnsKey.split(",");
					List values=(addedRow.toList(cols));
					getUniqueMap(columnsKey).put(esdk.obj.longHashCode(values),index);
				}
				index++;
			}
		}
		return this;
	}

	public ARowSet<T> updateUniqueIndex(@NonNull T changedRow,int pos){
		if(uniqueMap!=null){
			for(String columnsKey:uniqueMap.keySet()){
				String[] cols=columnsKey.split(",");
				getUniqueMap(columnsKey).put(esdk.obj.longHashCode(changedRow.toList(cols)),pos);
			}
		}
		return this;
	}

  @Override public T getRow(int i){
    checkRange(i);
    return (T)rowList.get(i);
  }

  protected final void checkRange(int i) {
    if(!isRange(i))
      throw new IndexOutOfBoundsException("index is "+i+" but size is "+rowList.size());
  }

	@Override  public int size(){
    return rowList.size();
  }

  public List<T> getRows(){
    return (List<T>)rowList;
  }

  public List<Map> toMapList(){
  	return toMapList(false);
  }

  public List<Map> toMapList(boolean isCamelCase){
  	ArrayList result=new ArrayList(this.size());
    for(int i=0;i<rowList.size();i++){
			IRow row=(IRow)rowList.get(i);
			result.add(row.toMap(isCamelCase));
		}
		return result;
  }

	public List<Map> toMapList(boolean isCamelCase,String[] columns){
		return toMapList(isCamelCase,columns,esdk.array.EmptyStrArr);
	}

	public List<Map> toMapList(boolean isCamelCase,String[] columns,String[] excludeCols){
  	ArrayList result=new ArrayList(this.size());
    for(int i=0;i<rowList.size();i++){
			IRow row=(IRow)rowList.get(i);
			if(esdk.array.isEmpty(excludeCols))
				result.add(row.toMap(isCamelCase,columns));
			else
				result.add(row.toMap(isCamelCase,columns,excludeCols));
		}
		return result;
  }

  /**默认输出驼峰格式，不输出扩展字段*/
	@Override
  public JSONArray toJsonArray(){
  	return toJsonArray(true);
  }

	@Override
	public JSONArray toJsonArray(boolean isCamelCase){
		return toJsonArray(isCamelCase,getColumns());
	}

	@Override
	public JSONArray toJsonArray(boolean isCamelCase,boolean isOutputExtraColumns){
		return toJsonArray(isCamelCase,isOutputExtraColumns?Constant.EmptyStrArr:getColumns());
	}

  public JSONArray toJsonArray(String... columns){
		return RowSetUtils.toJsonArray(this.toMapList(true,columns),false);
  }

	@Override
	public JSONArray toJsonArray(boolean isCamelCase,String... columns){
		return toJsonArray(isCamelCase,true,columns);
	}

  public JSONArray toJsonArray(boolean isCamelCase,boolean ifSnowIdToStr,String... columns){
		if(columns.length>0)
  		return RowSetUtils.toJsonArray(this.toMapList(isCamelCase,columns),isCamelCase,ifSnowIdToStr);
  	else
  		return RowSetUtils.toJsonArray(this.toMapList(isCamelCase),isCamelCase,ifSnowIdToStr);
  }

	@Override
	public JSONArray toJsonArray(boolean isCamelCase,boolean isOutputExtraColumns,String[] columns,String[] excludeColumns){
		if(esdk.array.isEmpty(columns))
			columns=getColumns();
		return RowSetUtils.toJsonArray(this.toMapList(isCamelCase,columns,excludeColumns),isCamelCase);
	}

	public <B> List<B> toBeanList(Class<B> beanCls){
		ArrayList result=new ArrayList(this.size());
		for(int i=0;i<rowList.size();i++){
			IRow row=(IRow)rowList.get(i);
			result.add(RowUtils.copyTo(row,esdk.reflect.safeNewInstance(beanCls),true));
		}
		return result;
	}

	/**为了方便调试，输出的格式不是csv也不是json，所以不能用作为业务数据内容输出，并且限制输出长度*/
  @Override public String toString(){
    StringBuilder result=new StringBuilder();
    int[] index=new int[]{0};
		for(int i=0,n=this.rowList.size();i<n;i++){
			IRow row=rowList.get(i);
			result.append((index[0]++)+"_"+row.getClass().getSimpleName()+row).append("\n");
			if(result.length()>10000){
				result.append("限制调试输出，只显示前"+(i+1)+"条记录...\n");
				break;
			}
		}
		if(result.length()>0)
			result.delete(result.length()-1,result.length());
    return result.toString();
  }

  @Override public boolean hasColumnName(String name){
    return esdk.array.contains(columns,name);
  }

  @Override public boolean isEmpty(){
    return rowList.size()==0;
  }

  public String toXml() {
  	ArrayList list=new ArrayList(rowList.size());
  	for(IRow row:rowList) {
  		list.add(row.toMap());
  	}
  	return XML.toXml(JSONUtil.parseArray(list),Constant.RowsetXmlIdentifier);
  }

  public String toXml(String[] labels) {
  	ArrayList list=new ArrayList(rowList.size());
  	for(IRow row:rowList) {
  		list.add(row.toMap(true,labels));
  	}
  	return XML.toXml(JSONUtil.parseArray(list),Constant.RowsetXmlIdentifier);
  }

  @Override  public String toCsv(){
  	return toCsv(getColumns());
  }

  public boolean toCsvFile(File file) throws IOException {
  	return esdk.file.saveToFile(toCsv(),file,true);
  }

  @Override  public String toCsv(String... labels){
    List<List> result=new ArrayList<>(rowList.size()+1);
    result.add(Arrays.asList(labels));
    try{
      for(Iterator iter=rowList.iterator();iter.hasNext();){
        IRow row=(IRow)iter.next();
        ArrayList<String> list=new ArrayList(labels.length);
        for(Iterator iterator=Arrays.asList(labels).iterator();iterator.hasNext();){
          String column=(String)iterator.next();
          Object content=row.get(column);
          list.add(EasyStr.getStringNoNull(content));
        }
        result.add(list);
      }
      return EasyStr.toCsv(result);
    }
    catch(Exception e){
      throw esdk.tool.wrapThrowble(e);
    }
  }

  public List<T> toList(){
  	return (List<T>)rowList;
  }

  @Override
  public Object[][] toArray2(){
  	String[] columns=getColumns();
  	Object[][] result=new Object[size()][columns.length];
  	for(int i=0;i<rowList.size();i++) {
  		IRow row=rowList.get(i);
  		Object[] arr=row.toList().toArray();
  		result[i]=arr;
  	}
  	return result;
  }

  @Override
  public Object[][] toArray2(boolean isOutputColumn,String... columns){
  	columns=columns.length==0?getColumns():columns;
  	Object[][] result=new Object[size()+(isOutputColumn?1:0)][columns.length];
  	if(isOutputColumn)
  		result[0]=columns;
  	for(int i=0;i<rowList.size();i++) {
  		IRow row=rowList.get(i);
  		Object[] arr=row.toList(columns).toArray();
  		result[isOutputColumn?i+1:i]=arr;
  	}
  	return result;
  }

  public List<List> toList2(){
  	return toList2(true,getColumns());
  }

	public List<List> toList2(boolean isOutputColumns,String... cols){
		List<List> result=new ArrayList<List>(rowList.size()+1);
		if(cols.length==0) cols=getColumns();
		if(isOutputColumns){
			result.add(Arrays.asList(cols));
		}
		for(Iterator iter=rowList.iterator();iter.hasNext();){
			IRow row=(IRow)iter.next();
			ArrayList list=new ArrayList(cols.length);
			for(Iterator iterator=Arrays.asList(cols).iterator();iterator.hasNext();){
				String column=(String)iterator.next();
				Object content=row.get(column);
				list.add(content);
			}
			result.add(list);
		}
		return result;
	}

	/*  @Override public ABRowSet<T> clone(){
	  ARowSet result;
			try{
				result=(ARowSet)super.clone();
				result.setColumns(this.getColumns());
		    for(IRow row:rowList){
		      result.add((IRow)row.clone());
		    }
		    return (ABRowSet<T>)result;
			}catch(CloneNotSupportedException e){
				throw esdk.tool.wrapThrowble(e);
			}
	}*/

  @Override public ARowSet<T> clone(){
	  try{
			ARowSet<T> result=(ARowSet<T>)super.clone();
			result.rowList=new ArrayList(this.size());
			result.rowList.addAll(this.rowList);
			result._rowCls=this._rowCls;
			return result;
		}catch(CloneNotSupportedException e){
			throw esdk.tool.wrapThrowble(e);
		}
	}

  @Override public Iterator<T> iterator() {
    return (Iterator<T>)rowList.iterator();
  }

  public <T extends IRow>T createRow() {
  	T result;
  	if(_abrs!=null&&_abrs instanceof ParentResultSet prs){
  		result=(T)prs.createRowInstance();
			((ParentRow)result).columns=this.columns;
  		RowUtils.fillDefaultVals((ParentRow)result);
  	}
  	else if(this._rowCls!=null) {
    	result=(T)esdk.reflect.safeNewInstance(_rowCls);
			((ParentRow)result).columns=this.columns;
			RowUtils.fillDefaultVals((ParentRow)result);
    }else {
    	result=(T)new ABRow(getColumns());
    }
  	return result;
  }

	/**使用lambda表达式过滤*/
	public ABRowSet<T> filter(Predicate<T> fn){
		return filter(0,fn);
	}

	/**使用lambda表达式过滤，只获取第1条件记录
	 * 注意：lambda的性能较for循环差很多，数据集超过200条不建议使用
	 * */
	public T filterFirst(Predicate<T> fn){
		return filter(1,fn).getFirstRow();
	}

	/**使用lambda表达式过滤，只获取第1条件记录
	 * 注意：lambda的性能较for循环差很多，数据集超过200条不建议使用
	 * 参数autoCreateInstance:是否自动创建一个新实例
	 * */
	public T filterFirst(Predicate<T> fn,boolean autoCreateInstance){
		return filter(1,fn).getFirstRow(autoCreateInstance);
	}

	/**使用lambda表达式过滤
	 * 注意：lambda的性能较for循环差很多，数据集超过200条不建议使用
	 * */
	public ABRowSet<T> filter(int top,Predicate<T> fn){
		ABRowSet<T> result=createRowset();
		if(top<=0)
			top=Integer.MAX_VALUE;
		for(T row:this) {
			if(fn.test(row)) {
				if(top-->0)
					result.addLast(row);
			}
		}
		return result;
	}

  @Override public ABRowSet<T> filter(IRowFilter filter) {
  	return RowSetUtils.filter(this,filter);
  }

  @Override public ABRowSet<T> filter(IExpression exp) {
  	return RowSetUtils.filter(this,new RowFilter(exp));
  }

	@Override
	public ABRowSet<T> filter(int top,IExpression exp){
		return RowSetUtils.filter(new ABRowSet(this),new RowFilter(exp),top);
	}

  public T filterFirst(String fieldName,Object equalValue) {
  	return filterFirst(fieldName,Expression.EQ,equalValue);
  }

	public T filterFirst(boolean autoCreateInstance,String expr){
		T result=filter(1,expr).getFirstRow(autoCreateInstance);
		return result;
	}

  public T filterFirst(boolean autoCreateInstance,String fieldName,Object equalValue) {
  	T result=filterFirst(fieldName,Expression.EQ,equalValue);
  	if(result==null && autoCreateInstance) {
  		result=createRow();
  		result.put(fieldName,equalValue);
  	}
  	return result;
  }

  /**
   * 注意：如果数据集超过1000条，sql查询的性能会优于使用filters，如果是等于条件，也可以使用findByUnique()，非首次搜索速度要快很多
   * */
  public T filterFirst(String fieldName,String expr,Object equalValue) {
  	return (T)RowSetUtils.filter(this,RowFilter.create(fieldName,expr,equalValue),1).getFirstRow();
  }

  /**
   * 注意：如果数据集超过1000条，sql查询的性能会优于使用filters，如果是等于条件，也可以使用findByUnique()，非首次搜索速度要快很多
   * @param autoCreateInstance：找不到的话自动创建Row实例
   * */
  public T filterFirst(boolean autoCreateInstance,String fieldName,String expr,Object equalValue) {
  	T result=(T)RowSetUtils.filter(this,RowFilter.create(fieldName,expr,equalValue),1).getFirstRow();
  	if(result==null && autoCreateInstance) {
  		result=createRow();
  		if(Exp.EQ.equals(expr))
  			result.put(fieldName,equalValue);
  	}
  	return result;
  }

  /**
   * 支持多个条件一次性过滤，推荐使用。
   * 注意：如果数据集超过1000条，sql查询的性能会优于使用filters，如果是等于条件，也可以使用findByUnique()，非首次搜索速度要快很多
   * @param autoCreateInstance：找不到的话自动创建Row实例
   * */
  public T filterFirst(boolean autoCreateInstance,String firstField,Object... args) {
  	T result=filters(1,firstField,args).getFirstRow();
  	if(result==null && autoCreateInstance) {
  		result=createRow();
  		Map<String,Object> map=findEqConditions(esdk.array.concat(Object.class,firstField,args));
  		result.load(map);
  	}
  	return result;
  }
	public T filterFirst(String firstField,Object... args) {
		return filterFirst(false,firstField,args);
	}
  public ABRowSet<T> filter(String fieldName,Object equalValue) {
  	return filter(RowFilter.create(fieldName,equalValue));
  }

  public ABRowSet<T> filter(String fieldName,String expression,Object equalValue) {
  	return filter(RowFilter.create(fieldName,expression,equalValue));
  }

  public ABRowSet<T> filter(int top,String fieldName,String expression,Object equalValue) {
  	return RowSetUtils.filter(this,RowFilter.create(fieldName,expression,equalValue),top);
  }

	public ABRowSet<T> filter(String fieldName,Collection collection) {
		return filter(RowFilter.create(fieldName,Exp.IN,collection));
	}
  /**
   * 支持where条件表达式进行查询，能对expr表达式进行分析出搜索条件，例如："(category=订单类型 && sequence>=10) && code!=001 || name in(张三,李四)"
   * 注意：如果数据集超过1000条，sql查询的性能会优于使用filters，如果是等于条件，也可以使用findByUnique()，非首次搜索速度要快很多
   * */
  public ABRowSet<T> filter(String expr) {
  	synchronized(this){
	  	ABRowSet<T> result=new ABRowSet<T>(this.getColumns());
	  	result.rowList=(new EasyQuery(getRows()).filter(expr).toList());
	  	return result;
  	}
  }

  /**
   * 支持where条件表达式进行查询，能对expr表达式进行分析出搜索条件，例如："(category=订单类型 && sequence>=10) && code!=001 || name in(张三,李四)"
   * 注意：如果数据集超过1000条，sql查询的性能会优于使用filters，如果是等于条件，也可以使用findByUnique()，非首次搜索速度要快很多
   * */
  public ABRowSet<T> filter(int top,String expr){
  	synchronized(this){
			ABRowSet<T> result=createRowset();
	  	try {
				result.load(new EasyQuery(this.getRows()).filter(expr,top).toList());
			} catch (Exception e) {
				throw new SQLRuntimeException(e);
			}
			return result;
		}
  }

	/**返回两个数据集的交集*/
	public ABRowSet<T> filter(IReadRowSet<T> rs){
		ABRowSet<T> result=createRowset();
		for(T row:rs){
			if(this.indexOf(row)>=0){
				result.addLast(row);
			}
		}
		return result;
	}

	/**创建一个新的Rowset实例*/
	public ABRowSet<T> createRowset(){
		ABRowSet result=new ABRowSet();
		result.columns=this.columns;
		result._rowCls=this._rowCls;
		result._abrs=this._abrs;
		result.primaryKeyName=this.primaryKeyName;
		return result;
	}
  public ABRowSet<T> filter(int top,String fieldName,Object equalValue) {
  	return filter(RowFilter.create(fieldName,equalValue).setTop(top));
  }

	/**可以一次输入多个and的条件，并支持所有的表达式。eg.: filter("name","张三",code,<>,test,"age","<",18)*/
	public ABRowSet<T> filters(String firstField,Object... args){
		args=esdk.array.concat(Object.class,firstField,args);
		RowExpressions expressions=new RowExpressions();
		String fieldValue=null,expression=Expression.EQ;
		Object rightValue=null;
		boolean isFieldValue=true;
		for(Object arg:args) {
			if(isFieldValue) {
				fieldValue=(String)arg;
				isFieldValue=false;
			}else if(EasyArray.contains(Expression.ALL,arg)) {
				expression=(String)arg;
			}else {
				rightValue=arg;
				expressions.add(fieldValue,expression,rightValue);
				isFieldValue=true;
				expression=Expression.EQ;
			}
		}
		return filter(expressions);
	}

	/**可以一次输入多个and的条件，并支持所有的表达式。eg.: filter("name","张三",code,<>,test,"age","<",18)
	 * 注意：如果数据集超过1000条，sql查询的性能会优于使用filters
	 * */
	public ABRowSet<T> filters(int top,String firstField,Object... args){
		args=esdk.array.concat(Object.class,firstField,args);
		RowFilter result=null;
		String fieldValue=null,expression=Expression.EQ;
		Object rightValue=null;
		boolean isFieldValue=true;
		for(Object arg:args) {
			if(isFieldValue) {
				fieldValue=(String)arg;
				isFieldValue=false;
			}else if(esdk.array.contains(Expression.ALL,arg)) {
				expression=(String)arg;
			}else {
				rightValue=arg;
				isFieldValue=true;
				if(result==null)
					result=RowFilter.create(fieldValue,expression,rightValue).setTop(top);
				else
					result.add(fieldValue,expression,rightValue);
				expression=Expression.EQ;
			}
		}
		return filter(result);
	}

	/**找出等于条件的值，用于自动赋值*/
	private Map<String,Object> findEqConditions(Object... args){
		HashMap<String,Object> result=new HashMap();
		String fieldValue=null,expression=Expression.EQ;
		Object rightValue=null;
		boolean isFieldValue=true;
		for(Object arg:args) {
			if(isFieldValue) {
				fieldValue=(String)arg;
				isFieldValue=false;
			}else if(esdk.array.contains(Expression.ALL,arg)) {
				expression=(String)arg;
			}else {
				rightValue=arg;
				isFieldValue=true;
				if(expression==Expression.EQ) {
					result.put(fieldValue,rightValue);
					if(rightValue!=null&&rightValue.getClass().equals(Date.class))
						result.put(fieldValue,new Timestamp(((Date)rightValue).getTime()));
				}
			}
		}
		return result;
	}

	/**对多个字段进行分组，以字段内容作为唯一值，把多条记录分配到多个记录集中*/
	@Override public List<ABRowSet<T>> group(String... fields) {
  	return RowSetUtils.group(this,fields);
  }

	/**对多个字段进行分组，以fn返回的值作为key，把多条记录分配到多个记录集中*/
	public List<ABRowSet<T>> group(Function<T,?> fn) {
		return RowSetUtils.group(this,fn);
	}

	/**对多个字段进行分组，以fn返回的值作为key，把多条记录分配到多个记录集中*/
	public <R> Map<R,ABRowSet<T>> groupMap(Function<T,R> fn) {
		return RowSetUtils.groupMap(new ABRowSet(this),fn);
	}

	/**使用lambda表达式修改记录内容*/
	public ABRowSet<T> update(Consumer<T> fn) {
		for(T row:this) {
			fn.accept(row);
		}
		return (ABRowSet<T>)this;
	}

	/**使用lambda表达式过滤*/
  public String[] getStrings(Function<T,String> fn) {
  	String[] result=new String[rowList.size()];
  	int i=0;
  	for(T row:this){
			result[i++]=fn.apply(row);
		}
  	return result;
  }

	/**使用lambda表达式过滤*/
  public Long[] getLongs(Function<T,Long> fn) {
  	Long[] result=new Long[rowList.size()];
  	int i=0;
  	for(T row:this){
			result[i++]=fn.apply(row);
		}
  	return result;
  }

	public EasyNumber<Number> reduce(Function<T,? extends Number> fn){
		EasyNumber result=new EasyNumber();
		for(T row:this){
			result.add(fn.apply(row));
		}
		return result;
	}

	public <Rtn extends Adder>Rtn reduce(Rtn result,Function<T,?> fn){
		for(T row:this){
			result.add(fn.apply(row));
		}
		return result;
	}

	/**使用lambda合计数量，可以用sum()代替*/
	public double reduceDbl(ToDoubleFunction<T> fn) {
		Double result=0D;
		for(T row:this){
			result+=fn.applyAsDouble(row);
		}
		return result;
	}

	/**使用lambda合计数量，可以用sum()代替*/
  public int reduceInt(ToIntFunction<T> fn) {
		int result=0;
		for(T row:this){
			result+=fn.applyAsInt(row);
		}
		return result;
	}

	/**使用lambda合计数量，可以用sum()代替*/
	public long reduceLong(ToLongFunction<T> fn) {
		long result=0;
		for(T row:this){
			result+=fn.applyAsLong(row);
		}
		return result;
	}

	/**使用lambda表达式过滤*/
	public <R> List<R> getList(Function<T,R> fn) {
		ArrayList result=new ArrayList();
		for(T row:this.rowList)
			result.add(fn.apply(row));
		return result;
	}

	/**
	 * 使用lambda表达式过滤
	 * @param distinct 去重
	 * */
	public <R> List<R> getList(Function<T,R> fn,boolean distinct) {
		ArrayList result=new ArrayList();
		for(T row:this.rowList){
			R r=fn.apply(row);
			if(!distinct || !result.contains(r))
				result.add(r);
		}
		return result;
	}

	/**得到某个字段的所有记录的内容*/
	@Override
	public String[] getStrings(String columnName){
		return RowSetUtils.getValues(rowList,columnName,String.class,true);
	}

	@Override
	public Integer[] getIntegers(String columnName){
		return RowSetUtils.getValues(rowList,columnName,Integer.class);
	}

	@Override
	public Object[] getObjects(String columnName){
		return RowSetUtils.getValues(rowList,columnName,Object.class);
	}

	@Override
	public Double[] getDoubles(String columnName){
		return RowSetUtils.getValues(rowList,columnName,Double.class);
	}

	public String[] getStrings(String columnName,boolean isDistinct) {
		return RowSetUtils.getValues(rowList,columnName,String.class,isDistinct);
	}
	public Integer[] getIntegers(String columnName,boolean isDistinct) {
		return RowSetUtils.getValues(rowList,columnName,Integer.class,isDistinct);
	}
	public Long[] getLongs(String columnName) {
		return RowSetUtils.getValues(rowList,columnName,Long.class);
	}
	public Long[] getLongs(String columnName,boolean isDistinct) {
		return RowSetUtils.getValues(rowList,columnName,Long.class,isDistinct);
	}
  public Double[] getDoubles(String columnName,boolean isDistinct) {
		return RowSetUtils.getValues(rowList,columnName,Double.class,isDistinct);
  }
	public Number[] getNumbers(String columnName) {
		return RowSetUtils.getValues(rowList,columnName,Number.class);
	}
	public Number[] getNumbers(String columnName,boolean isDistinct) {
		return RowSetUtils.getValues(rowList,columnName,Number.class,isDistinct);
	}
	public Object[] getObjects(String columnName,boolean isDistinct) {
		return RowSetUtils.getValues(rowList,columnName,Object.class,isDistinct);
	}
	public BigDecimal[] getBigDecimals(String columnName) {
		return RowSetUtils.getValues(rowList,columnName,BigDecimal.class);
	}
	public BigDecimal[] getBigDecimals(String columnName,boolean isDistinct) {
		return RowSetUtils.getValues(rowList,columnName,BigDecimal.class,isDistinct);
	}
	public Date[] getDates(String columnName) {
		return RowSetUtils.getValues(rowList,columnName,Date.class);
	}
	public Date[] getDates(String columnName,boolean isDistinct) {
		return RowSetUtils.getValues(rowList,columnName,Date.class,isDistinct);
	}
	public LocalDate[] getLocalDates(String columnName,boolean isDistinct) {
		return RowSetUtils.getValues(rowList,columnName,LocalDate.class,isDistinct);
	}
	public LocalDate[] getLocalDates(String columnName) {
		return RowSetUtils.getValues(rowList,columnName,LocalDate.class);
	}
	public LocalDateTime[] getLocalDateTimes(String columnName) {
		return RowSetUtils.getValues(rowList,columnName,LocalDateTime.class);
	}
	public LocalDateTime[] getLocalDateTimes(String columnName,boolean isDistinct) {
		return RowSetUtils.getValues(rowList,columnName,LocalDateTime.class,isDistinct);
	}

	public List getValues(String columnName){
		return RowSetUtils.getValues(rowList,columnName,true);
	}
	public List getValues(String columnName,boolean isDistinct){
		return RowSetUtils.getValues(rowList,columnName,isDistinct);
	}

	public String toString(String field,String delimiter){
		return esdk.array.toStr(getValues(field,true),delimiter+"");
	}

	public BigDecimal decimalSum(String...columns){
		BigDecimal result=new BigDecimal(0);
		for(int i=0,n=rowList.size();i<n;i++){
			IRow row=(IRow)rowList.get(i);
			for(int j=0;j<columns.length;j++){
				if((row).get(columns[j])!=null)
					result = result.add(row.getBigDecimal(columns[j]));
			}
		}
		return result;
	}

	/**合计总数量*/
	@Override public EasyNumber sum(String...columns) {
		EasyNumber result=new EasyNumber();
		for(int i=0,n=rowList.size();i<n;i++){
			IRow row=(IRow)rowList.get(i);
			for(int j=0;j<columns.length;j++){
				if((row).get(columns[j])!=null)
					result.add((Number)(row).get(columns[j]));
			}
		}
		return result;
	}

	public EasyNumber<Number> sum(Function<T,? extends Number> fn){
		return reduce(fn);
	}

  /**取平均值*/
  public EasyNumber average(String...columns){
  	return sum(columns).divide(size());
  }

  /**取最大值*/
  public Number max(String...columns) {
  	Number result=null;
  	for(int i=0;i<columns.length;i++) {
  		Number max=esdk.math.max(getNumbers(columns[i]));
  		if(result==null)
  			result=max;
  		else
  			result=esdk.math.max(max,result);
  	}
    return result;
  }

  /**取最小值*/
  public Number min(String...columns) {
  	Number result=null;
  	for(int i=0;i<columns.length;i++) {
  		Number min=esdk.math.min(getNumbers(columns[i]));
  		if(result==null)
  			result=min;
  		else
  			result=esdk.math.min(min,result);
  	}
    return result;
  }

  /**取最大值*/
  public Object maxObj(String...columns) {
  	Comparable result=null;
  	for(int i=0;i<columns.length;i++) {
  		Comparable max=esdk.obj.max((Comparable[])getValues(columns[i]).toArray(new Comparable[0]));
  		if(result==null)
  			result=max;
  		else
  			result=esdk.obj.max(max,result);
  	}
    return result;
  }

  /**取最小值*/
  public Comparable minObj(String...columns) {
  	Comparable result=null;
  	for(int i=0;i<columns.length;i++) {
  		Comparable min=esdk.obj.min((Comparable[])getValues(columns[i]).toArray(new Comparable[0]));
  		if(result==null)
  			result=min;
  		else
  			result=esdk.obj.min(min,result);
  	}
    return result;
  }

  public T getFirstRow() {
  	return size()>0?getRow(0):null;
  }

  public T getFirstRow(boolean autoCreateInstance) {
  	return size()>0?getRow(0):autoCreateInstance?createRow():null;
  }

  public T getLastRow(){
  	return size()>0?getRow(this.size()-1):null;
  }

	public T getLastRow(boolean autoCreateInstance) {
		return size()>0?getRow(this.size()-1):autoCreateInstance?createRow():null;
	}

  @Override public ABRowSet<T> sort(String... columnKeys) {
    return sort(false,columnKeys);
  }

	@Override public ABRowSet<T> sort(final boolean isDesc,final String...cols){
		if(!isEmpty()){
				Collections.sort(this.rowList,(o1,o2)->{
					if(o1==o2) return 0;
					int result=0;
          if(o1==null) result=-1;
          if(o2==null) result=1;
					if(result!=0&&isDesc)
						result=esdk.obj.revserse(result);
					else {
						for(int i=0;result==0&&i<cols.length;i++){
							result=EasyObj.compareTo(o1.get(cols[i]),o2.get(cols[i]),isDesc);
						}
					}
					return result;
				});
		}
		return (ABRowSet<T>)this;
	}

	/**创建新的数据集并复制字段结构*/
	@Override
	public <RS extends IResultSet> RS of(){
		return (RS)new ABRowSet(this.getColumns());
	}

  public ABRowSet<T> subRowSet(int start,int limit) {
  	int adjustStart=EasyMath.max(EasyMath.min(start,rowList.size()),0);
  	int adjustLimit=adjustStart+EasyMath.min(esdk.math.max(limit,0),EasyMath.max(rowList.size()-adjustStart,0));
  	List<T> subList=this.rowList.subList(adjustStart,adjustLimit);
  	if(subList!=null) {
	  	ABRowSet result=new ABRowSet(this.getColumns()).load(subList);
	  	result._abrs=this._abrs;
	  	return result;
  	}else
  		return of();
  }

	public void setPrimaryKeyName(String primaryKeyFieldName) {
		this.primaryKeyName= primaryKeyFieldName;
	}

	public String getPrimaryKeyName() {
		if(primaryKeyName==null){
			if(rowList.size()>0 && getFirstRow() instanceof ParentRow<?> pr)
				primaryKeyName=pr.getPrimaryKeyName();
			else if(_rowCls!=null && esdk.tool.asSubClass(_rowCls,ParentRow.class))
				primaryKeyName=((ParentRow)esdk.reflect.safeNewInstance(_rowCls)).getPrimaryKeyName();
			else
				primaryKeyName=columns[0];
		}
		return primaryKeyName;
	}

	public int indexOf(IRow row) {
		if (EasyObj.isValid(getPrimaryKeyName())) {
			for (int i = 0, n = this.size(); i < n; i++) {
				if (this.getRow(i).get(getPrimaryKeyName()).equals(row.get(getPrimaryKeyName())))
					return i;
			}
			return -1;
		} else {
			return getRows().indexOf(row);
		}
	}
  @Override  public void afterLast(){
    cursor=rowList.size();
  }

  public void beforeFirst(){
    cursor=-1;
  }

  @Override public boolean first(){
  	cursor=0;
    return(isRange((cursor)));
  }

  @Override public int getCursor(){
    if(isRange(cursor))
      return cursor;
    else
      return -1;
  }

  public boolean last(){
  	cursor=rowList.size()-1;
    return isRange(cursor);
  }

  @Override public boolean next(){
    return isRange(++cursor);
  }

  @Override public boolean absolute(int i){
  	cursor=i;
    return isRange(cursor);
  }

  @Override public IRow getCurrentRow(){
    return getRow(cursor);
  }

  @Override public boolean isAfterLast(){
    return cursor>=rowList.size();
  }

  @Override public boolean isBeforeFirst(){
    return cursor<0;
  }

  @Override public boolean isFirst(){
    return cursor==0;
  }

  @Override public boolean isLast(){
    return cursor==rowList.size()-1;
  }

  @Override public boolean previous(){
    return isRange(--cursor);
  }

  @Override public boolean relative(int offset){
    boolean result=isRange(cursor+offset);
    if(result) cursor+=offset;
    return result;
  }

  public int totalCount() {
  	return ((ABResultSet)_abrs).totalCount();
  }

	public void setTotalCount(int totalCount){
		((ABResultSet)_abrs).fillTotalCount(totalCount);
	}
}
